package com.unswift.utils;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.LinkedHashMap;
import java.util.Map;

import com.unswift.QuickApplication;
import com.unswift.constant.QuickConstant;
import com.unswift.window.factory.MessageFactory;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

public class DbSession {

	public static HikariDataSource instance;
	
	public synchronized static void setInstance(String driver, String url, String username, String password) {
		HikariConfig config=new HikariConfig();
		config.setMinimumIdle(Integer.parseInt(QuickApplication.getConfig(QuickConstant.CONF_HIKARI_POOL_MINIMUM_IDLE)));
		config.setIdleTimeout(Long.parseLong(QuickApplication.getConfig(QuickConstant.CONF_HIKARI_POOL_IDLE_TIMEOUT)));
		config.setMaximumPoolSize(Integer.parseInt(QuickApplication.getConfig(QuickConstant.CONF_HIKARI_POOL_MAXIMUM_POOL_SIZE)));
		config.setAutoCommit(Boolean.parseBoolean(QuickApplication.getConfig(QuickConstant.CONF_HIKARI_POOL_AUTO_COMMIT)));
		config.setMaxLifetime(Long.parseLong(QuickApplication.getConfig(QuickConstant.CONF_HIKARI_POOL_MAX_LIFETIME)));
		config.setConnectionTimeout(Long.parseLong(QuickApplication.getConfig(QuickConstant.CONF_HIKARI_POOL_CONNECTION_TIMEOUT)));
		config.setConnectionTestQuery(QuickApplication.getConfig(QuickConstant.CONF_HIKARI_POOL_CONNECTION_TEST_QUERY));
		config.setDriverClassName(driver);
		config.setJdbcUrl(url);
		config.setUsername(username);
		config.setPassword(password);
		instance=new HikariDataSource(config);
	}
	
	public static void find(String sql, FindDataBack back, Object...args){
		Connection conn=null;
		PreparedStatement pstmt=null;
		ResultSet rs=null;
		try {
			conn=instance.getConnection();
			pstmt=conn.prepareStatement(sql);
			if(ObjectUtils.isNotEmpty(args)){
				for (int i = 0, length=args.length; i < length; i++) {
					pstmt.setObject(i+1, args[i]);
				}
			}
			rs=pstmt.executeQuery();
			ResultSetMetaData metaData = rs.getMetaData();
			int length=metaData.getColumnCount();
			String columnName;
			Object columnValue;
			Map<String, Object> rowData;
			int row=0;
			while(rs.next()){
				rowData=new LinkedHashMap<String, Object>();
				for (int i = 0; i < length; i++) {
					columnName=metaData.getColumnLabel(i+1);
					columnValue = rs.getObject(columnName);
					if(ObjectUtils.isNotEmpty(columnValue)){
						if(columnValue instanceof Date){
							rowData.put(columnName, DateUtils.format((Date)columnValue, "yyyy-MM-dd"));
						}else if(columnValue instanceof Time){
							rowData.put(columnName, DateUtils.format((Time)columnValue, "HH:mm:ss"));
						}else if(columnValue instanceof Timestamp){
							rowData.put(columnName, DateUtils.format((Timestamp)columnValue, "yyyy-MM-dd HH:mm:ss"));
						}else if(columnValue instanceof java.util.Date){
							rowData.put(columnName, DateUtils.format((java.util.Date)columnValue, "yyyy-MM-dd HH:mm:ss"));
						}else{
							rowData.put(columnName, columnValue);
						}
					}else{
						rowData.put(columnName, columnValue);
					}
				}
				back.handleRow(rowData, row);
				row++;
			}
			back.endData(row);
		} catch (Exception e) {
			MessageFactory.error(QuickApplication.getWindow(), "数据库查询异常，消息："+e.getMessage());
			e.printStackTrace();
		} finally {
			try {
				rs.close();
				pstmt.close();
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	
	public static int execute(String sql, Object...args){
		Connection conn=null;
		PreparedStatement pstmt=null;
		try {
			conn=instance.getConnection();
			pstmt=conn.prepareStatement(sql);
			if(ObjectUtils.isNotEmpty(args)){
				for (int i = 0, length=args.length; i < length; i++) {
					pstmt.setObject(i+1, args[i]);
				}
			}
			return pstmt.executeUpdate();
		} catch (Exception e) {
			MessageFactory.error(QuickApplication.getWindow(), "数据库查询异常，消息："+e.getMessage());
			e.printStackTrace();
			throw ExceptionUtils.exception("database.execute.exception", e, e.getMessage());
		} finally {
			try {
				pstmt.close();
				conn.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
	}
	
	public static abstract class FindDataBack {

		public boolean handleRow(Map<String, Object> rowData, int row){return true;};

		public void endData(int row){};
		
	}
}
